import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.fisco.bcos.sdk.abi.FunctionReturnDecoder;
import org.fisco.bcos.sdk.abi.TypeReference;
import org.fisco.bcos.sdk.abi.datatypes.Event;
import org.fisco.bcos.sdk.abi.datatypes.Function;
import org.fisco.bcos.sdk.abi.datatypes.Type;
import org.fisco.bcos.sdk.abi.datatypes.Utf8String;
import org.fisco.bcos.sdk.abi.datatypes.generated.Uint256;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple1;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple2;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple3;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.contract.Contract;
import org.fisco.bcos.sdk.crypto.CryptoSuite;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.eventsub.EventCallback;
import org.fisco.bcos.sdk.model.CryptoType;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.model.callback.TransactionCallback;
import org.fisco.bcos.sdk.transaction.model.exception.ContractException;

@SuppressWarnings("unchecked")
public class PointSystem extends Contract {
    public static final String[] BINARY_ARRAY = {"608060405234801561001057600080fd5b50611542806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80633e0fdd511161005b5780633e0fdd5114610397578063547ca487146104525780635cc49f63146105c2578063f851a440146107325761007d565b806310e5c74d146100825780632afd97a4146101f95780633a51d246146102c8575b600080fd5b6101dc6004803603606081101561009857600080fd5b81019080803590602001906401000000008111156100b557600080fd5b8201836020820111156100c757600080fd5b803590602001918460018302840111640100000000831117156100e957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561014c57600080fd5b82018360208201111561015e57600080fd5b8035906020019184600183028401116401000000008311171561018057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803590602001909291905050506107b5565b604051808381526020018281526020019250505060405180910390f35b6102b26004803603602081101561020f57600080fd5b810190808035906020019064010000000081111561022c57600080fd5b82018360208201111561023e57600080fd5b8035906020019184600183028401116401000000008311171561026057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610b76565b6040518082815260200191505060405180910390f35b610381600480360360208110156102de57600080fd5b81019080803590602001906401000000008111156102fb57600080fd5b82018360208201111561030d57600080fd5b8035906020019184600183028401116401000000008311171561032f57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610ba4565b6040518082815260200191505060405180910390f35b610450600480360360208110156103ad57600080fd5b81019080803590602001906401000000008111156103ca57600080fd5b8201836020820111156103dc57600080fd5b803590602001918460018302840111640100000000831117156103fe57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610c17565b005b6105ac6004803603606081101561046857600080fd5b810190808035906020019064010000000081111561048557600080fd5b82018360208201111561049757600080fd5b803590602001918460018302840111640100000000831117156104b957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561051c57600080fd5b82018360208201111561052e57600080fd5b8035906020019184600183028401116401000000008311171561055057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190929190505050610d58565b6040518082815260200191505060405180910390f35b61071c600480360360608110156105d857600080fd5b81019080803590602001906401000000008111156105f557600080fd5b82018360208201111561060757600080fd5b8035906020019184600183028401116401000000008311171561062957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803590602001909291908035906020019064010000000081111561069657600080fd5b8201836020820111156106a857600080fd5b803590602001918460018302840111640100000000831117156106ca57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610ffe565b6040518082815260200191505060405180910390f35b61073a6112da565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561077a57808201518184015260208101905061075f565b50505050905090810190601f1680156107a75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600080826001866040518082805190602001908083835b602083106107ef57805182526020820191506020810190506020830392506107cc565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020541015610897576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f496e73756666696369656e742062616c616e636500000000000000000000000081525060200191505060405180910390fd5b826001866040518082805190602001908083835b602083106108ce57805182526020820191506020810190506020830392506108ab565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060008282540392505081905550826001856040518082805190602001908083835b602083106109455780518252602082019150602081019050602083039250610922565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020600082825401925050819055507f35139bb0b8452f0c3c8cc7968bf977e9313424deee574cebf108b955bee7992e858585604051808060200180602001848152602001838103835286818151815260200191508051906020019080838360005b838110156109f35780820151818401526020810190506109d8565b50505050905090810190601f168015610a205780820380516001836020036101000a031916815260200191505b50838103825285818151815260200191508051906020019080838360005b83811015610a59578082015181840152602081019050610a3e565b50505050905090810190601f168015610a865780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a16001856040518082805190602001908083835b60208310610acc5780518252602082019150602081019050602083039250610aa9565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020546001856040518082805190602001908083835b60208310610b365780518252602082019150602081019050602083039250610b13565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390205491509150935093915050565b6001818051602081018201805184825260208301602085012081835280955050505050506000915090505481565b60006001826040518082805190602001908083835b60208310610bdc5780518252602082019150602081019050602083039250610bb9565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020549050919050565b60008080546001816001161561010002031660029004905014610ca2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f41646d696e20616c72656164792073657400000000000000000000000000000081525060200191505060405180910390fd5b8060009080519060200190610cb8929190611467565b507f4edd2806dd503ea14082eb8e4d93fbe5da941eca86b51e762adf6cfac65f98e8816040518080602001828103825283818151815260200191508051906020019080838360005b83811015610d1b578082015181840152602081019050610d00565b50505050905090810190601f168015610d485780820380516001836020036101000a031916815260200191505b509250505060405180910390a150565b6000610dfe8460008054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610df45780601f10610dc957610100808354040283529160200191610df4565b820191906000526020600020905b815481529060010190602001808311610dd757829003601f168201915b5050505050611378565b610e70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f4f6e6c792061646d696e2063616e20697373756520706f696e7473000000000081525060200191505060405180910390fd5b816001846040518082805190602001908083835b60208310610ea75780518252602082019150602081019050602083039250610e84565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020600082825401925050819055507f4756447a265d62d6c0f2a68a90758f41900904d82a40f4104153398add221e6e83836040518080602001838152602001828103825284818151815260200191508051906020019080838360005b83811015610f50578082015181840152602081019050610f35565b50505050905090810190601f168015610f7d5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a16001836040518082805190602001908083835b60208310610fc15780518252602082019150602081019050602083039250610f9e565b6001836020036101000a0380198251168184511680821785525050505050","5090500191505090815260200160405180910390205490509392505050565b6000826001856040518082805190602001908083835b602083106110375780518252602082019150602081019050602083039250611014565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390205410156110df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f496e73756666696369656e742062616c616e636500000000000000000000000081525060200191505060405180910390fd5b826001856040518082805190602001908083835b6020831061111657805182526020820191506020810190506020830392506110f3565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020600082825403925050819055507f867b85649eda2c2cf02dacb03426655de0aa8b12894a19bd72dfbb5de343117d848484604051808060200184815260200180602001838103835286818151815260200191508051906020019080838360005b838110156111c45780820151818401526020810190506111a9565b50505050905090810190601f1680156111f15780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b8381101561122a57808201518184015260208101905061120f565b50505050905090810190601f1680156112575780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a16001846040518082805190602001908083835b6020831061129d578051825260208201915060208101905060208303925061127a565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390205490509392505050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156113705780601f1061134557610100808354040283529160200191611370565b820191906000526020600020905b81548152906001019060200180831161135357829003601f168201915b505050505081565b6000816040516020018082805190602001908083835b602083106113b1578051825260208201915060208101905060208303925061138e565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b602083106114235780518252602082019150602081019050602083039250611400565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106114a857805160ff19168380011785556114d6565b828001600101855582156114d6579182015b828111156114d55782518255916020019190600101906114ba565b5b5090506114e391906114e7565b5090565b61150991905b808211156115055760008160009055506001016114ed565b5090565b9056fea2646970667358221220f4a67252382fd560619ea03bab72fe6d6d25ae8108a0ae3a3b0765435b21466564736f6c634300060a0033"};

    public static final String BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", BINARY_ARRAY);

    public static final String[] SM_BINARY_ARRAY = {};

    public static final String SM_BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", SM_BINARY_ARRAY);

    public static final String[] ABI_ARRAY = {"[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"newAdmin\",\"type\":\"string\"}],\"name\":\"AdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"user\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"PointsConsumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"to\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PointsIssued\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"from\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"to\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PointsTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"caller\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"consumePoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"caller\",\"type\":\"string\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"caller\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"to\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"issuePoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"newAdmin\",\"type\":\"string\"}],\"name\":\"setAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"from\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"to\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferPoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"};

    public static final String ABI = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", ABI_ARRAY);

    public static final String FUNC_ADMIN = "admin";

    public static final String FUNC_BALANCES = "balances";

    public static final String FUNC_CONSUMEPOINTS = "consumePoints";

    public static final String FUNC_GETBALANCE = "getBalance";

    public static final String FUNC_ISSUEPOINTS = "issuePoints";

    public static final String FUNC_SETADMIN = "setAdmin";

    public static final String FUNC_TRANSFERPOINTS = "transferPoints";

    public static final Event ADMINSET_EVENT = new Event("AdminSet", 
            Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
    ;

    public static final Event POINTSCONSUMED_EVENT = new Event("PointsConsumed", 
            Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Uint256>() {}, new TypeReference<Utf8String>() {}));
    ;

    public static final Event POINTSISSUED_EVENT = new Event("PointsIssued", 
            Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Uint256>() {}));
    ;

    public static final Event POINTSTRANSFERRED_EVENT = new Event("PointsTransferred", 
            Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}, new TypeReference<Uint256>() {}));
    ;

    protected PointSystem(String contractAddress, Client client, CryptoKeyPair credential) {
        super(getBinary(client.getCryptoSuite()), contractAddress, client, credential);
    }

    public static String getBinary(CryptoSuite cryptoSuite) {
        return (cryptoSuite.getCryptoTypeConfig() == CryptoType.ECDSA_TYPE ? BINARY : SM_BINARY);
    }

    public List<AdminSetEventResponse> getAdminSetEvents(TransactionReceipt transactionReceipt) {
        List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(ADMINSET_EVENT, transactionReceipt);
        ArrayList<AdminSetEventResponse> responses = new ArrayList<AdminSetEventResponse>(valueList.size());
        for (Contract.EventValuesWithLog eventValues : valueList) {
            AdminSetEventResponse typedResponse = new AdminSetEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.newAdmin = (String) eventValues.getNonIndexedValues().get(0).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public void subscribeAdminSetEvent(String fromBlock, String toBlock, List<String> otherTopics, EventCallback callback) {
        String topic0 = eventEncoder.encode(ADMINSET_EVENT);
        subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    }

    public void subscribeAdminSetEvent(EventCallback callback) {
        String topic0 = eventEncoder.encode(ADMINSET_EVENT);
        subscribeEvent(ABI,BINARY,topic0,callback);
    }

    public List<PointsConsumedEventResponse> getPointsConsumedEvents(TransactionReceipt transactionReceipt) {
        List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(POINTSCONSUMED_EVENT, transactionReceipt);
        ArrayList<PointsConsumedEventResponse> responses = new ArrayList<PointsConsumedEventResponse>(valueList.size());
        for (Contract.EventValuesWithLog eventValues : valueList) {
            PointsConsumedEventResponse typedResponse = new PointsConsumedEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.user = (String) eventValues.getNonIndexedValues().get(0).getValue();
            typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue();
            typedResponse.reason = (String) eventValues.getNonIndexedValues().get(2).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public void subscribePointsConsumedEvent(String fromBlock, String toBlock, List<String> otherTopics, EventCallback callback) {
        String topic0 = eventEncoder.encode(POINTSCONSUMED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    }

    public void subscribePointsConsumedEvent(EventCallback callback) {
        String topic0 = eventEncoder.encode(POINTSCONSUMED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,callback);
    }

    public List<PointsIssuedEventResponse> getPointsIssuedEvents(TransactionReceipt transactionReceipt) {
        List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(POINTSISSUED_EVENT, transactionReceipt);
        ArrayList<PointsIssuedEventResponse> responses = new ArrayList<PointsIssuedEventResponse>(valueList.size());
        for (Contract.EventValuesWithLog eventValues : valueList) {
            PointsIssuedEventResponse typedResponse = new PointsIssuedEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.to = (String) eventValues.getNonIndexedValues().get(0).getValue();
            typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public void subscribePointsIssuedEvent(String fromBlock, String toBlock, List<String> otherTopics, EventCallback callback) {
        String topic0 = eventEncoder.encode(POINTSISSUED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    }

    public void subscribePointsIssuedEvent(EventCallback callback) {
        String topic0 = eventEncoder.encode(POINTSISSUED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,callback);
    }

    public List<PointsTransferredEventResponse> getPointsTransferredEvents(TransactionReceipt transactionReceipt) {
        List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(POINTSTRANSFERRED_EVENT, transactionReceipt);
        ArrayList<PointsTransferredEventResponse> responses = new ArrayList<PointsTransferredEventResponse>(valueList.size());
        for (Contract.EventValuesWithLog eventValues : valueList) {
            PointsTransferredEventResponse typedResponse = new PointsTransferredEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.from = (String) eventValues.getNonIndexedValues().get(0).getValue();
            typedResponse.to = (String) eventValues.getNonIndexedValues().get(1).getValue();
            typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public void subscribePointsTransferredEvent(String fromBlock, String toBlock, List<String> otherTopics, EventCallback callback) {
        String topic0 = eventEncoder.encode(POINTSTRANSFERRED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    }

    public void subscribePointsTransferredEvent(EventCallback callback) {
        String topic0 = eventEncoder.encode(POINTSTRANSFERRED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,callback);
    }

    public String admin() throws ContractException {
        final Function function = new Function(FUNC_ADMIN, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
        return executeCallWithSingleValueReturn(function, String.class);
    }

    public BigInteger balances(String param0) throws ContractException {
        final Function function = new Function(FUNC_BALANCES, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(param0)), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeCallWithSingleValueReturn(function, BigInteger.class);
    }

    public TransactionReceipt consumePoints(String caller, BigInteger amount, String reason) {
        final Function function = new Function(
                FUNC_CONSUMEPOINTS, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(caller), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(reason)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public void consumePoints(String caller, BigInteger amount, String reason, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_CONSUMEPOINTS, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(caller), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(reason)), 
                Collections.<TypeReference<?>>emptyList());
        asyncExecuteTransaction(function, callback);
    }

    public String getSignedTransactionForConsumePoints(String caller, BigInteger amount, String reason) {
        final Function function = new Function(
                FUNC_CONSUMEPOINTS, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(caller), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(reason)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple3<String, BigInteger, String> getConsumePointsInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_CONSUMEPOINTS, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Uint256>() {}, new TypeReference<Utf8String>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple3<String, BigInteger, String>(

                (String) results.get(0).getValue(), 
                (BigInteger) results.get(1).getValue(), 
                (String) results.get(2).getValue()
                );
    }

    public Tuple1<BigInteger> getConsumePointsOutput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getOutput();
        final Function function = new Function(FUNC_CONSUMEPOINTS, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple1<BigInteger>(

                (BigInteger) results.get(0).getValue()
                );
    }

    public BigInteger getBalance(String caller) throws ContractException {
        final Function function = new Function(FUNC_GETBALANCE, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(caller)), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeCallWithSingleValueReturn(function, BigInteger.class);
    }

    public TransactionReceipt issuePoints(String caller, String to, BigInteger amount) {
        final Function function = new Function(
                FUNC_ISSUEPOINTS, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(caller), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(to), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public void issuePoints(String caller, String to, BigInteger amount, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_ISSUEPOINTS, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(caller), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(to), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)), 
                Collections.<TypeReference<?>>emptyList());
        asyncExecuteTransaction(function, callback);
    }

    public String getSignedTransactionForIssuePoints(String caller, String to, BigInteger amount) {
        final Function function = new Function(
                FUNC_ISSUEPOINTS, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(caller), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(to), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple3<String, String, BigInteger> getIssuePointsInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_ISSUEPOINTS, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}, new TypeReference<Uint256>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple3<String, String, BigInteger>(

                (String) results.get(0).getValue(), 
                (String) results.get(1).getValue(), 
                (BigInteger) results.get(2).getValue()
                );
    }

    public Tuple1<BigInteger> getIssuePointsOutput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getOutput();
        final Function function = new Function(FUNC_ISSUEPOINTS, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple1<BigInteger>(

                (BigInteger) results.get(0).getValue()
                );
    }

    public TransactionReceipt setAdmin(String newAdmin) {
        final Function function = new Function(
                FUNC_SETADMIN, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(newAdmin)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public void setAdmin(String newAdmin, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_SETADMIN, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(newAdmin)), 
                Collections.<TypeReference<?>>emptyList());
        asyncExecuteTransaction(function, callback);
    }

    public String getSignedTransactionForSetAdmin(String newAdmin) {
        final Function function = new Function(
                FUNC_SETADMIN, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(newAdmin)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple1<String> getSetAdminInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_SETADMIN, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple1<String>(

                (String) results.get(0).getValue()
                );
    }

    public TransactionReceipt transferPoints(String from, String to, BigInteger amount) {
        final Function function = new Function(
                FUNC_TRANSFERPOINTS, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(from), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(to), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public void transferPoints(String from, String to, BigInteger amount, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_TRANSFERPOINTS, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(from), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(to), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)), 
                Collections.<TypeReference<?>>emptyList());
        asyncExecuteTransaction(function, callback);
    }

    public String getSignedTransactionForTransferPoints(String from, String to, BigInteger amount) {
        final Function function = new Function(
                FUNC_TRANSFERPOINTS, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(from), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(to), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple3<String, String, BigInteger> getTransferPointsInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_TRANSFERPOINTS, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}, new TypeReference<Uint256>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple3<String, String, BigInteger>(

                (String) results.get(0).getValue(), 
                (String) results.get(1).getValue(), 
                (BigInteger) results.get(2).getValue()
                );
    }

    public Tuple2<BigInteger, BigInteger> getTransferPointsOutput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getOutput();
        final Function function = new Function(FUNC_TRANSFERPOINTS, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}, new TypeReference<Uint256>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple2<BigInteger, BigInteger>(

                (BigInteger) results.get(0).getValue(), 
                (BigInteger) results.get(1).getValue()
                );
    }

    public static PointSystem load(String contractAddress, Client client, CryptoKeyPair credential) {
        return new PointSystem(contractAddress, client, credential);
    }

    public static PointSystem deploy(Client client, CryptoKeyPair credential) throws ContractException {
        return deploy(PointSystem.class, client, credential, getBinary(client.getCryptoSuite()), "");
    }

    public static class AdminSetEventResponse {
        public TransactionReceipt.Logs log;

        public String newAdmin;
    }

    public static class PointsConsumedEventResponse {
        public TransactionReceipt.Logs log;

        public String user;

        public BigInteger amount;

        public String reason;
    }

    public static class PointsIssuedEventResponse {
        public TransactionReceipt.Logs log;

        public String to;

        public BigInteger amount;
    }

    public static class PointsTransferredEventResponse {
        public TransactionReceipt.Logs log;

        public String from;

        public String to;

        public BigInteger amount;
    }
}
